package com.hitqz.robot.biz.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.util.concurrent.RateLimiter;
import com.hitqz.robot.api.business.dto.RobotControlButtonDto;
import com.hitqz.robot.api.business.dto.RobotEquipmentControlButtonDto;
import com.hitqz.robot.api.business.dto.RobotWarningDto;
import com.hitqz.robot.api.business.entity.RobotJobEntity;
import com.hitqz.robot.api.business.util.ExcelUtil;
import com.hitqz.robot.api.dispatch.protocol.dto.UploadMediaUrlDto;
import com.hitqz.robot.biz.config.CustomConstant;
import com.hitqz.robot.biz.service.RobotClientCmdService;
import com.hitqz.robot.biz.service.RobotJobService;
import com.hitqz.robot.common.core.util.R;
import com.hitqz.robot.api.business.dto.CmdRobot2PosDto;
import com.hitqz.robot.common.core.util.RedisUtils;
import com.hitqz.robot.daemon.quartz.entity.SysJob;
import com.hitqz.robot.daemon.quartz.service.SysJobService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;

import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

/**
 * 执行端控制
 *
 * @author wengyongxin
 * @date 2024-05-28 08:21:06
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/client/cmd" )
@Tag(description = "client" , name = "执行端控制" )
//@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
@Slf4j
public class RobotClientCmdController {

	private final RobotClientCmdService robotClientCmdService;

    private final RobotJobService robotJobService;

    private final SysJobService sysJobService;

	private final RateLimiter limiter = RateLimiter.create(5);

	@Operation(summary = "执行端控制" , description = "下发命令到执行端" )
    @PostMapping("/{clientId}" )
    public R<Boolean> send(@PathVariable(value = "clientId") String clientId,
						   @RequestBody RobotControlButtonDto button){
		if (!limiter.tryAcquire(1)){
			return R.ok();
		}
		log.info("to clientId:{},robot button: {}",clientId,button.getAction());
		return R.ok(robotClientCmdService.sendRobotCtrl(clientId,button));
    }


	@Operation(summary = "执行端外设控制" , description = "下发命令到执行端" )
	@PostMapping("/{clientId}/equipment" )
	public void sendEquipmentCtrl(@PathVariable(value = "clientId") String clientId,
						   @RequestBody RobotEquipmentControlButtonDto button,
							HttpServletResponse response){
		if (limiter.tryAcquire(1)){
			log.info("to clientId:{},equipment button: {}",clientId,button.getAction());
            String customButtonResult = dealCustomButton(button, response);
            if (StrUtil.isNotBlank(customButtonResult)){
                ExcelUtil.response2Web(response,customButtonResult);
                return;
            }
			robotClientCmdService.sendEquipmentCtrl(clientId,button);
			try {
				if (Objects.equals(button.getPostType(), "download-picture")|| Objects.equals(button.getPostType(), "download-video")) {
					Thread.sleep(5000);
					String dto = RedisUtils.get("mediaUpload:" + clientId);
					if (StrUtil.isNotBlank(dto)) {
						UploadMediaUrlDto uploadMediaUrlDto = JSON.parseObject(dto, UploadMediaUrlDto.class);
						response.setContentType("application/octet-stream");
						response.setCharacterEncoding("utf-8");
						response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + uploadMediaUrlDto.getName());
						ServletOutputStream outputStream = response.getOutputStream();
						URL url = URLUtil.url(uploadMediaUrlDto.getMediaUrl());
						try (InputStream inputStream = url.openStream()) {
							byte[] buffer = new byte[4096];
							int bytesRead;
							while ((bytesRead = inputStream.read(buffer)) != -1) {
								outputStream.write(buffer, 0, bytesRead);
							}
						}finally {
							outputStream.close();
						}
						return;
					}
				}
			} catch (Exception e) {
				log.error("拍照/录像失败,{}",e.getMessage());
			}
		}
		ExcelUtil.response2Web(response,"指令下发成功");
	}

    private String dealCustomButton(RobotEquipmentControlButtonDto button, HttpServletResponse response) {
        if (Objects.equals(button.getAction(),"custom-mode")){
            if (CustomConstant.modeEnable.get() && CustomConstant.plcStatus.get()){
                return "请先关闭皮带状态";
            }
            CustomConstant.modeEnable.set(!CustomConstant.modeEnable.get());
            return "操作成功";
        }
        if(Objects.equals(button.getAction(),"custom-plc")){
            if (!CustomConstant.modeEnable.get()){
                return "请先启用联动模式";
            }
            CustomConstant.plcStatus.set(!CustomConstant.plcStatus.get());
            if (CustomConstant.plcStatus.get()){
                RobotJobEntity job = robotJobService.getOne(Wrappers.<RobotJobEntity>lambdaQuery().like(RobotJobEntity::getName,"%联动%").last("limit 1"));
                job.setEnable(1);
                robotJobService.updateById(job);
                SysJob sysJob = sysJobService.getOne(Wrappers.<SysJob>lambdaQuery().eq(SysJob::getMethodParamsValue, String.valueOf(job.getId())).last("limit 1"));
                if (sysJob != null) {
                    try {
                        sysJobService.runOneJob(sysJob.getJobId());
                        Thread.sleep(1000);
                        sysJobService.startJob(sysJob.getJobId());
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            }else{
                RobotJobEntity job = robotJobService.getOne(Wrappers.<RobotJobEntity>lambdaQuery().like(RobotJobEntity::getName,"%联动%").last("limit 1"));
                job.setEnable(0);
                robotJobService.updateById(job);
                SysJob sysJob = sysJobService.getOne(Wrappers.<SysJob>lambdaQuery().eq(SysJob::getMethodParamsValue, String.valueOf(job.getId())).last("limit 1"));
                if (sysJob != null) {
                    try {
                        sysJobService.pauseJob(sysJob.getJobId());
                    } catch (SchedulerException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
            return "操作成功";
        }
        return "";
    }


    @Operation(summary = "执行端控制", description = "前往某个站点")
	@PostMapping("/goStation/{clientId}/{posCode}")
	public R goStation(@PathVariable(value = "clientId") String clientId,
					   @PathVariable(value = "posCode") String posCode) {
		CmdRobot2PosDto dto = new CmdRobot2PosDto();
		dto.setClientId(clientId);
		dto.setPosCode(posCode);
		SpringUtil.getApplicationContext().publishEvent(dto);
		return R.ok();
	}

	@Operation(summary = "执行端控制", description = "报警标记已读")
	@PostMapping("/warning/{clientId}")
	public R warning(@PathVariable(value = "clientId") String clientId,
					   @RequestBody Integer[] ids) {
		for (Integer id : ids) {
			RobotWarningDto dto = new RobotWarningDto();
			dto.setId(Long.parseLong(String.valueOf(id)));
			robotClientCmdService.sendReadWarning(clientId,dto);
		}
		return R.ok();
	}

    @Operation(summary = "执行端控制", description = "视觉报警关闭")
    @GetMapping("/visionWarning/{clientId}")
    public R visionWarning(@PathVariable(value = "clientId") String clientId) {
        RobotControlButtonDto request = new RobotControlButtonDto();
        request.setName("关闭视觉告警声");
        request.setAction("closeVisionWarning");
        request.setLongClick(false);
        request.setPostType("post");
        HashMap<String, Object> map = new HashMap<>();
        map.put("cmd",0);
        request.setParam(map);
        request.setDataType("json");
        request.setShowBtnPicUrl("");
        request.setClickedBtnPicUrl("");
        request.setMapAction("");
        request.setIconNotAllow("");
        robotClientCmdService.sendRobotCtrl(clientId,request);
        return R.ok();
    }


	//@Operation(summary = "执行端控制", description = "前往某个站点")
	//@PostMapping("/goStation/{clientId}/{posId}")
	//public R goStation(@PathVariable(value = "clientId") String clientId,
	//				   @PathVariable(value = "posId") Integer posId) {
	//
	//	return R.ok();
	//}

	@GetMapping("/{clientId}/voiceRequest")
	@Operation(summary = "语音请求")
	public R voiceRequest(@PathVariable(value = "clientId") String clientId,
						  @RequestParam(value = "cmd") int cmd) throws InterruptedException {
		// 0 - 取消语音请求
		// 1 - 语音请求
		RobotControlButtonDto request = new RobotControlButtonDto();
		request.setName("语音请求开启");
		request.setAction("voiceRequest");
		request.setLongClick(false);
		request.setPostType("post");
		HashMap<String, Object> map = new HashMap<>();
		map.put("cmd",1);
		request.setParam(map);
		request.setDataType("json");
		request.setShowBtnPicUrl("");
		request.setClickedBtnPicUrl("");
		request.setMapAction("");
		request.setIconNotAllow("");
		RobotControlButtonDto cancel = new RobotControlButtonDto();
		cancel.setName("语音请求关闭");
		cancel.setAction("voiceRequest");
		cancel.setLongClick(false);
		cancel.setPostType("post");
		HashMap<String, Object> cancelMap = new HashMap<>();
		cancelMap.put("cmd",0);
		cancel.setParam(cancelMap);
		cancel.setDataType("json");
		cancel.setShowBtnPicUrl("");
		cancel.setClickedBtnPicUrl("");
		cancel.setMapAction("");
		cancel.setIconNotAllow("");
		if (cmd == 0){
			robotClientCmdService.sendRobotCtrl(clientId,cancel);
		}
		if (cmd == 1){
			robotClientCmdService.sendRobotCtrl(clientId,request);
		}
		Thread.sleep(1500);
		return R.ok();
	}

}